#ifndef GRAPHWIDGET_H
#define GRAPHWIDGET_H

#include <QGLWidget>
#include <QColor>
#include <QPen>
#include <QTimer>

#include "GraphWidgetObject.h"
#include "GraphWidgetLine.h"
#include "GraphWidgetHistogram.h"

namespace Ui {
    class GraphWidget;
}

class GraphWidget : public QGLWidget
{
    Q_OBJECT

public:
    explicit GraphWidget(QWidget *parent = 0);
    ~GraphWidget();

    float getXInterval();
    float getXTickMarkLength();
    float getYInterval();
    float getYTickMarkLength();

    float getAxesWidth();
    float getSelectedObjectWidth();
    QColor getAxesColor();
    QColor getBackgroundColor();
    QColor getSelectedObjectColor();

    void setIntervalCounts(float x, float y);
    void setTickMarkLengthRatios(float x, float y);
    void setXIntervalCount(float interval);
    void setXTickMarkLengthRatio(float length);
    void setYIntervalCount(float interval);
    void setYTickMarkLengthRatio(float length);

    void setAxesWidth(float width);
    void setSelectedObjectWidth(float width);
    void setAxesColor(QColor color);
    void setBackgroundColor(QColor color);
    void setSelectedObjectColor(QColor color);

    int getSelectedObjectIndex();
    void setSelectedObjectIndex(int index);

public slots:
    void saveToImage();
    QImage toImage();
    void setTitle(QString title);
    void setTitleColor(QColor color);
    void autoResizeWindowRect();
    void setWindowRect(QRectF rect);
    void setWindowRect(float xMin, float xMax, float yMin, float yMax);
    void graphHistogram(QVector<int> histogramValues, bool graphInYDirection = true, double start = 0, double interval = 1, QColor color = Qt::white, float width = 1.0f, QString title = QString());
    void graphHistogram(QVector<float> histogramValues, bool graphInYDirection = true, double start = 0, double interval = 1, QColor color = Qt::white, float width = 1.0f, QString title = QString());
    void graphHistogram(QVector<double> histogramValues, bool graphInYDirection = true, double start = 0, double interval = 1, QColor color = Qt::white, float width = 1.0f, QString title = QString());
    void graphHistogram(QVector<QPointF> values, QColor color = Qt::white, float width = 1.0f, QString title = QString());
    void graphHistogram(GraphWidgetHistogram line);
    void graphLine(QVector<int> yValues, double xStart = 0, double xInterval = 1, QColor color = Qt::white, float width = 1.0f, QString title = QString());
    void graphLine(QVector<float> yValues, double xStart = 0, double xInterval = 1, QColor color = Qt::white, float width = 1.0f, QString title = QString());
    void graphLine(QVector<double> yValues, double xStart = 0, double xInterval = 1, QColor color = Qt::white, float width = 1.0f, QString title = QString());
    void graphLine(QVector<QPointF> values, QColor color = Qt::white, float width = 1.0f, QString title = QString());
    void graphLine(QLine newLine, QColor color = Qt::white, float width = 1.0f, QString title = QString());
    void graphLine(QLineF newLine, QColor color = Qt::white, float width = 1.0f, QString title = QString());
    void graphLine(GraphWidgetLine line);
    void graphObject(GraphWidgetObject* line);
    void graphMultipleObjectsAtIntervals(QVector<QVector<GraphWidgetObject*> >& objectLists, int milliseconds = 1000);
    void graphObjectsAtIntervals(QVector<GraphWidgetObject*>& objectList, int milliseconds = 1000);
    void zoomAtPoint(QPointF point, float scaleFactor);
    void translateAmount(float x, float y);
    int findLineIndexClosestToPoint(QPointF point);
    void toggleObjectSelect(int index);
    void reset();


protected:
    void resizeGL(int w, int h);
    void initializeGL();
    void paintGL();
    void mousePressEvent(QMouseEvent* event);
    void mouseMoveEvent(QMouseEvent* event);
    void mouseReleaseEvent(QMouseEvent* event);
    void keyPressEvent(QKeyEvent* event);
    void wheelEvent(QWheelEvent* event);
    QPointF translatePoint(QPointF point);

private slots:
    QLineF getXAxis();
    QLineF getYAxis();
    void drawLine(QPointF* line, int pointCount, QPen pen);
    void drawLine(QVector<QPointF>& line, QPen pen);
    void drawLine(float x1, float y1, float x2, float y2, QPen pen);
    void drawLine(QPointF point1, QPointF point2, QPen pen);
    void drawLine(QLineF line, QPen pen);
    void drawAxesCoord(float coord, float x, float y, bool isX);
    void drawAxes();
    void highlightSelectedLine();
    void drawTracePoint();
    void drawObjects();
    void drawTitle();
    void drawText(QString text, float x, float y, bool isWorldCoordinates = true, float size = 12, QColor color = Qt::white,
                  bool shouldHighlight = false, QColor highlightColor = Qt::black);
    void drawRect(float left, float top, float right, float bottom, bool isWorldCoordinates = true,
                  QColor color = Qt::black, bool shouldKeepOriginalSize = false);
    void drawTraceCoords();
    void drawLegend();
    void traceValueEntered();
    void graphNextIntervalObjectList();

private:
    Ui::GraphWidget *ui;
    QRectF windowRect;
    float xIntervalCount;
    float yIntervalCount;
    float xTickMarkLengthRatio;
    float yTickMarkLengthRatio;
    QPen axesPen;
    QColor backgroundColor;
    QVector<GraphWidgetObject*> objects;
    QPointF mouseStartingPoint;
    QPointF mouseMovingPoint;
    int selectedObjectIndex;
    QPen selectedObjectPen;
    QPointF tracePoint;
    bool shouldDrawTraceCoords;
    QString graphTitle;
    QColor graphTitleColor;
    bool shouldDrawLegend;

    enum selectedLineType {
        NO_LINE = -1
    };

    QVector<QVector<GraphWidgetObject*> > intervalObjectLists;
    QTimer timer;

};

#endif // GRAPHWIDGET_H
